package org.server.action.actionController.room;

import com.alibaba.fastjson.JSON;
import com.iohao.game.action.skeleton.annotation.ActionController;
import com.iohao.game.action.skeleton.annotation.ActionMethod;
import com.iohao.game.action.skeleton.core.ActionCommand;
import com.iohao.game.action.skeleton.core.ActionCommandFlowExecute;
import com.iohao.game.action.skeleton.core.flow.FlowContext;
import com.iohao.game.action.skeleton.core.flow.FlowContextFactory;
import com.iohao.game.bolt.broker.client.external.session.UserSessions;
import lombok.extern.slf4j.Slf4j;
import org.server.action.ActionCmd;
import org.server.common.BroadcastUtils;
import org.server.common.exception.CustomException;
import org.server.domain.Login.MyAttachment;
import org.server.domain.Result.Msg;
import org.server.domain.Room.Poker;
import org.server.domain.Room.RoomName;
import org.server.service.LoginService;
import org.server.service.RoomService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * @author Admin
 */
@Slf4j
@Component
@ActionController(ActionCmd.ROOM)
public class RoomAction {

    @Autowired
    private RoomService roomService;
    @Autowired
    private LoginService loginService;

    /**
     * 创建房间
     *
     * @param flowContext
     * @return org.server.domain.RoomMsg
     * @author Tang
     * @date 2023/3/1 0:13
     **/
    @ActionMethod(ActionCmd.ROOM_CREATE)
    public void createRoom(FlowContext flowContext) {
        //玩家id
        long userId = flowContext.getUserId();
        //生成房间名
        String roomName = (flowContext.getUserId() + UUID.randomUUID().toString()).substring(0, 5);
        try {
            //创建房间
            roomService.createRoom(roomName, userId);
            BroadcastUtils.broadcast(ActionCmd.ROOM, ActionCmd.ROOM_CREATE, new Msg(roomName), userId);
        } catch (CustomException e) {
            BroadcastUtils.broadcast(ActionCmd.ROOM, ActionCmd.ROOM_CREATE, new Msg(e.getMsg()), userId);
        }
    }

    /**
     * 加入房间
     *
     * @param roomJoin
     * @param flowContext
     * @return org.server.domain.Result.Msg<org.server.common.Type>
     * @author Tang
     * @date 2023/3/1 9:52
     **/
    @ActionMethod(ActionCmd.ROOM_JOIN)
    public Msg joinRoom(RoomName roomJoin, FlowContext flowContext) {
        long userId = flowContext.getUserId();
        MyAttachment attachment = flowContext.getAttachment(MyAttachment.class);
        String userName = attachment.getUserNickName();
        try {
            String roomName = roomJoin.roomName;
            List<Long> userIds = roomService.joinRoom(roomName, userId);
            BroadcastUtils.broadcast(ActionCmd.MSG, ActionCmd.MSG_BROADCAST, new Msg(userName + "加入房间"), userIds);
            this.broadcastRoomPlayerInfo(userIds);
            return new Msg("true");
        } catch (CustomException e) {
            BroadcastUtils.broadcast(ActionCmd.MSG, ActionCmd.MSG_BROADCAST, new Msg(e.getMsg()), userId);
        } catch (NullPointerException e) {
            BroadcastUtils.broadcast(ActionCmd.MSG, ActionCmd.MSG_BROADCAST, new Msg("系统错误"), userId);
        }
        return new Msg("false");
    }

    /**
     * 离开房间
     *
     * @param roomLeft
     * @param flowContext
     * @return org.server.domain.Result.Msg
     * @author Tang
     * @date 2023/4/18 13:48
     **/
    @ActionMethod(ActionCmd.ROOM_LEFT)
    public Msg left(RoomName roomLeft, FlowContext flowContext) {
        long userId = flowContext.getUserId();
        MyAttachment attachment = flowContext.getAttachment(MyAttachment.class);
        if (attachment == null) {
            attachment = loginService.getMyAttachment(userId);
        }
        String userName = attachment.getUserNickName();
        try {
            String roomName = roomLeft.roomName;
            List<Long> userIds = roomService.leftRoom(roomName, userId);
            if (userIds != null && userIds.size() != RoomService.MIN_PLAYER) {
                BroadcastUtils.broadcast(ActionCmd.MSG, ActionCmd.MSG_BROADCAST, new Msg(userName + "离开房间"), userIds);
                this.broadcastRoomPlayerInfo(userIds);
            }
            return new Msg("true");
        } catch (CustomException e) {
            BroadcastUtils.broadcast(ActionCmd.MSG, ActionCmd.MSG_BROADCAST, new Msg(e.getMsg()), userId);
        }
        return new Msg("false");
    }

    /**
     * 玩家准备
     *
     * @param roomReady
     * @return org.server.domain.Result.Msg
     * @author Tang
     * @date 2023/4/18 13:48
     **/
    @ActionMethod(ActionCmd.ROOM_READY)
    public void ready(RoomName roomReady, FlowContext flowContext) {
        String roomName = roomReady.roomName;
        long userId = flowContext.getUserId();
        MyAttachment attachment = flowContext.getAttachment(MyAttachment.class);
        String userName = attachment.getUserNickName();
        try {
            List<Long> userIds = roomService.ready(roomName, userId);
            BroadcastUtils.broadcast(ActionCmd.MSG, ActionCmd.MSG_BROADCAST, new Msg(userName + "准备"), userIds);
        } catch (CustomException e) {
            BroadcastUtils.broadcast(ActionCmd.MSG, ActionCmd.MSG_BROADCAST, new Msg(e.getMsg()), userId);
        }
    }

    /**
     * 玩家取消准备
     *
     * @param roomCancelReady
     * @param flowContext
     * @return void
     * @author Tang
     * @date 2023/4/18 23:48
     **/
    @ActionMethod(ActionCmd.ROOM_CANCEL_READY)
    public void cancelReady(RoomName roomCancelReady, FlowContext flowContext) {
        String roomName = roomCancelReady.roomName;
        long userId = flowContext.getUserId();
        MyAttachment attachment = flowContext.getAttachment(MyAttachment.class);
        String userName = attachment.getUserNickName();
        try {
            List<Long> userIds = roomService.cancelReady(roomName, userId);
            BroadcastUtils.broadcast(ActionCmd.MSG, ActionCmd.MSG_BROADCAST, new Msg(userName + "取消准备"), userIds);
        } catch (CustomException e) {
            BroadcastUtils.broadcast(ActionCmd.MSG, ActionCmd.MSG_BROADCAST, new Msg(e.getMsg()), userId);
        }
    }

    /**
     * 玩家出牌
     *
     * @param poker
     * @param flowContext
     * @return org.server.domain.Result.Msg
     * @author Tang
     * @date 2023/4/24 10:46
     **/
    @ActionMethod(ActionCmd.ROOM_PLAY)
    public Msg play(Poker poker, FlowContext flowContext) {
        long userId = flowContext.getUserId();
        try {
            poker.setIsTrue(poker.getIsTrue() == null ? 0 : 1);
            List<Long> userIds = roomService.play(poker, userId);
            BroadcastUtils.broadcast(ActionCmd.POKER, ActionCmd.POKER_PLAY, new Msg(JSON.toJSONString(poker.getFakePoker())), userIds);
//            BroadcastUtils.broadcast(ActionCmd.MSG, ActionCmd.MSG_BROADCAST, new Msg(JSON.toJSONString(poker.getFakePoker())), userIds);
            BroadcastUtils.broadcast(ActionCmd.ROOM,ActionCmd.ROOM_TIMER_OFF,new Msg(),userIds);
            return new Msg("true");
        } catch (CustomException e) {
            BroadcastUtils.broadcast(ActionCmd.MSG, ActionCmd.MSG_BROADCAST, new Msg(e.getMsg()), userId);
        }
        return new Msg("false");
    }

    /**
     * 玩家过牌
     *
     * @param poker
     * @param flowContext
     * @return org.server.domain.Result.Msg
     * @author Tang
     * @date 2023/4/24 10:54
     **/
    @ActionMethod(ActionCmd.ROOM_PASS)
    public Msg pass(Poker poker, FlowContext flowContext) {
        long userId = flowContext.getUserId();
        MyAttachment attachment = flowContext.getAttachment(MyAttachment.class);
        String userName = attachment.getUserNickName();
        try {
            List<Long> userIds = roomService.pass(poker, userId);
            BroadcastUtils.broadcast(ActionCmd.MSG, ActionCmd.MSG_BROADCAST, new Msg(userName + "过牌"), userIds);
            BroadcastUtils.broadcast(ActionCmd.ROOM,ActionCmd.ROOM_TIMER_OFF,new Msg(),userIds);
            return new Msg("true");
        } catch (CustomException e) {
            BroadcastUtils.broadcast(ActionCmd.MSG, ActionCmd.MSG_BROADCAST, new Msg(e.getMsg()), userId);
        }
        return new Msg("false");
    }

    /**
     * 玩家质疑
     *
     * @param poker
     * @param flowContext
     * @return org.server.domain.Result.Msg
     * @author Tang
     * @date 2023/4/24 22:39
     **/
    @ActionMethod(ActionCmd.ROOM_QUESTION)
    public Msg question(Poker poker, FlowContext flowContext) {
        long userId = flowContext.getUserId();
        MyAttachment attachment = flowContext.getAttachment(MyAttachment.class);
        String userName = attachment.getUserNickName();
        try {
            List<Long> userIds = roomService.question(poker, userId);
            BroadcastUtils.broadcast(ActionCmd.MSG, ActionCmd.MSG_BROADCAST, new Msg(userName + "进行质疑"), userIds);
            BroadcastUtils.broadcast(ActionCmd.ROOM,ActionCmd.ROOM_TIMER_OFF,new Msg(),userIds);
            return new Msg("true");
        } catch (CustomException e) {
            BroadcastUtils.broadcast(ActionCmd.MSG, ActionCmd.MSG_BROADCAST, new Msg(e.getMsg()), userId);
        }
        return new Msg("false");
    }

    private void broadcastRoomPlayerInfo(List<Long> playerList) {
        //通知玩家的出牌顺序
        for (Long playerId : playerList) {
            //玩家顺序
            int currentOrder = playerList.indexOf(playerId);
            BroadcastUtils.broadcast(ActionCmd.ROOM, ActionCmd.ROOM_PLAYER_ORDER, new Msg(Integer.toString(currentOrder)), playerId);
        }
        List<MyAttachment> players = new ArrayList<>();
        for (Long aLong : playerList) {
            players.add(loginService.getMyAttachment(aLong));
        }
        log.info(players.toString());
        //广播当前的玩家列表
        BroadcastUtils.broadcast(ActionCmd.ROOM, ActionCmd.ROOM_PLAYER_LIST, new Msg(JSON.toJSONString(players)), playerList);
    }
}
